﻿/*
 * 作者：DHclly
 * 描述:获取验证码
 * 实现：可设置输出位数，验证码图片宽高
 * 
 */
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace IceDog.DNF.Library.Common.Captcha
{
    /// <summary>
    /// 获取验证码
    /// </summary>
    public class SimpleValidationCode
    {
        private static readonly string _charStr = "2,3,4,5,6,7,8,9,A,B,C,D,E,F,G,H,J,K,L,M,N,P,Q,R,S,T,U,X,Y,Z";//去除容易出错的字符
        private readonly Random _ran;
        private Bitmap _img;
        private readonly int _count;
        private readonly int _width;
        private readonly int _height;
        /// <summary>
        /// 验证码文字
        /// </summary>
        public string Code { get; set; }
        /// <summary>
        /// 验证码图片
        /// </summary>
        public Bitmap CodeImage { get; set; }
        /// <summary>
        /// 刷新验证码的方法
        /// </summary>
        public void Refresh()
        {
            Code = GetRandomCode(_count);
            CodeImage = GetImage(Code, _width, _height);
        }
        private SimpleValidationCode()
        {
            _ran = new Random();
        }
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="count">显示字符数量</param>
        /// <param name="width">图片宽度，单位px</param>
        /// <param name="height">图片高度，单位px</param>
        public SimpleValidationCode(int count, int width, int height) : this()
        {
            _count = count;
            _width = width;
            _height = height;
            Refresh();
        }
        ~SimpleValidationCode()
        {
            CodeImage.Dispose();
        }
        //获取验证码
        private string GetRandomCode(int count)
        {
            string[] charArr = _charStr.Split(',');
            var len = charArr.Length;
            int tempIndex = -1;
            var result = string.Empty;
            for (int i = 0; i < count; i++)
            {
                var newIndex = _ran.Next(len);
                if (newIndex == tempIndex)//如果连续是相同的字符，重新来一次
                {
                    newIndex = _ran.Next(len);
                }
                tempIndex = newIndex;
                result += charArr[newIndex];
            }
            return result;
        }

        private Bitmap GetImage(string content, int width, int height)
        {
            _img = new Bitmap(width, height);
            Graphics g = Graphics.FromImage(_img);//获取img 对象的gdi+对象
            Font font = new Font(new FontFamily("Arial"), 16, FontStyle.Italic);
            Brush brush = new LinearGradientBrush(new Rectangle(0, 0, width, height), GetRandomColor(0, 100), GetRandomColor(100, 150), 45F, true);
            g.Clear(Color.White);//设置背景色
            //绘制背景噪音线
            for (int i = 0; i < 10; i++)
            {
                g.DrawBezier(new Pen(GetRandomColor(155, 225), 2), GetRandomPoint(width, height), GetRandomPoint(width, height), GetRandomPoint(width, height), GetRandomPoint(width, height));
            }
            //绘制内容
            g.DrawString(content, font, brush, 4, 2);
            //绘制前景噪音点
            for (int i = 0; i < 25; i++)
            {
                var p = GetRandomPoint(width, height);
                _img.SetPixel(p.X, p.Y, Color.Black);
            }
            //绘制边框
            //g.DrawRectangle(new Pen(Color.Black),0,0,width-1,height-1 );
            return _img;
        }

        private Point GetRandomPoint(int maxX, int maxY)
        {
            return new Point()
            {
                X = _ran.Next(maxX),
                Y = _ran.Next(maxY)
            };
        }

        private Color GetRandomColor(int min = 0, int max = 255)
        {
            return Color.FromArgb(_ran.Next(min, max), _ran.Next(min, max), _ran.Next(min, max));
        }

        public static void Run()
        {
            Console.WriteLine("请看当前方法的注释");
            //用法如下
            //SimpleValidationCode validationCode = new SimpleValidationCode(4,100,200);
            //var code = validationCode.Code;
            //var img = validationCode.CodeImage;
            //validationCode.Refresh();
            //
            //在网页中应用,MVC4下
            //MemoryStream stream = new MemoryStream();
            //img.Save(stream, ImageFormat.Jpeg);
            //Response.ClearContent();
            //Response.ContentType = "image/jpeg";
            //Response.BinaryWrite(stream.ToArray());
            //var httpCookie = Response.Cookies["code"];
            //if (httpCookie != null) httpCookie.Value = code;
            //页面引用
            //<img src="@Url.Action("GetImg")" />
            //在win form中则如下使用即可
            //textBox1.Text = validationCode.Code;
            //pictureBox1.Image = validationCode.CodeImage;
        }
    }
}
